package fi.solita.dojo.mazeserver.game

import swing._
import fi.solita.dojo.mazeserver.ui._
import scala.collection._
import scala.collection.mutable._
import fi.solita.dojo.mazeserver.game.internal._
import fi.solita.dojo.mazeserver.map._

case class GameWorld (map: GameMap, playerList: PlayerList) {}

object GameWorld extends swing.Publisher{

	private var world: GameWorld = GameWorld(randomMap, new PlayerList(Nil))

	var running = false

	def map(): GameMap = world.map

	def playerList(): PlayerList = world.playerList

	def collectPoint(p: Player) = {
		if (world.map(p.coordinates).point) {
			setMap(map.removePoint(p.coordinates))
			p.addPoint
		} else p
	}

	private[game] def setMap(m: GameMap) {
		world = GameWorld(m, world.playerList)
	}

	private def setPlayerList(pl: PlayerList) {
		world = GameWorld(world.map, pl)
	}

	private[game] def executeActions(): Unit = {
			for (p <- playerList.players) {
				setPlayerList(playerList.execute(p))
			}
			clearAllActions()
	}

	private[game] def clearAllActions() {
		playerList.players foreach (setAction(_, None))
	}

	private[game] def setAction(p: Player, a: Option[GameAction]): Unit = {
			setPlayerList(playerList().replace(p.setAction(a)))
	}

	private[game] def reservedName(name: String) = playerList.reservedName(name)

	private[game] def initialLocation(): Coordinates = {
			val c = map().randomPassableCoordinates
			playerList.playerAt(c) match {
			case None => c
			case Some(_) => initialLocation
			}
	}


	private[game] def addPlayer(name: String) {
		setPlayerList(playerList.addPlayer(name))
		publish(PlayersAddedEvent(playerList))
	} 

	private[game] def removePlayer(name: String) {
		setPlayerList(playerList.removePlayer(name))
		publish(PlayersLeftEvent(playerList))
	}

	def locationOf(loc: GameLocation): Coordinates = {
			(map().locations filter (_._2 == loc)).elements.next._1
	}  

	def publishUIEvents() {
		publish(GameChangedEvent(map, playerList))
		publish(PlayersUpdatedEvent(playerList))
	} 

	def newMap() = {
		setMap(randomMap)
		setPlayerList(playerList.reset)
		running = false
	}
 
	def randomMap(): GameMap = MapGenerator.createSimpleMap(10,10)
}

